import type {DataConnection, MediaConnection} from "peerjs";
import Peer from "peerjs";
import {hasAudioTrack} from "@/utils/my_media_device.js"

enum CallStatus { //无通话、等待通话、正在通话
    Noting,
    Call,
    Talking
}
enum Signal {
    CANCEL = "cancel",
    ACCEPT = "accept",
    REJECT = "reject",
    HANGUP = "hangup",
    SetCallType = "setCallType",
}

class SignalMessage {
    sender: string;
    receiver: string;
    command: Signal;
    extend: string; //扩展字段

    constructor(options: { sender: string; receiver: string; command: Signal; extend: string}) {
        this.sender = options.sender;
        this.receiver = options.receiver;
        this.command = options.command;
        this.extend = options.extend;
    }
}

/**
 * 发起者
 */
class Caller {
    userId: string;
    calleeId: string;
    peer: any;
    dataConn?: DataConnection;
    conn?: MediaConnection;
    localStream?: MediaStream;
    contact: any;// 对方的基本信息（name、头像等）

    constructor(userId: string, calleeId: string, /*contact: any,*/ peer: Peer) {
        this.userId = userId; // 自己的id
        this.calleeId = calleeId; // 被呼叫人的id
        this.dataConn = null;
        this.conn = null;
        this.localStream = null;
        // this.contact = contact;

        this.peer = peer;
    }

    /**
     * 发起呼叫
     * 只是发起呼叫动作，等待对方的回应：拒接or接听
     */
    call(callType:number,callback: any) {
        //创建和对方的连接
        this.dataConn = this.peer.connect(this.calleeId); //DataConnection
        this.dataConn.on('open', () => {
            console.log("已和对方连通...");
            this.dataConn?.send(new SignalMessage({sender: this.userId, receiver: this.calleeId, command: Signal.SetCallType,extend:String(callType)}))
        })
        // Receive messages
        this.dataConn.on('data', (msg) => {
            console.log('Received: ' + JSON.stringify(msg));
            if (!msg) {
                return;
            }
            callback((msg as SignalMessage).command);
        });
    }

    /**
     * 真正的开始通话
     * @param remoteVideo
     */
    doTalk(remoteVideo: any) {
        const mediaConn = this.peer.call(this.calleeId, this.localStream); //MediaConnection
        mediaConn.on('stream', (stream: MediaStream) => {
            console.debug(`>>> 远端流 stream.id=${stream.id}. 是否含有音轨? ${hasAudioTrack(stream)} `)
            //播放远端的stream
            remoteVideo.srcObject = stream;
            // 监听canplay事件，确保媒体就绪后再播放
            remoteVideo.addEventListener('canplay', () => {
                remoteVideo.play().catch(err => {
                    console.error('播放错误:', err);
                });
            });
        });
        this.conn = mediaConn;
    }

    /**
     * 取消呼叫
     */
    cancel() {
        this.dataConn?.send(new SignalMessage({sender: this.userId, receiver: this.calleeId, command: Signal.CANCEL}))
        this.close();
    }

    hangup() {
        try{
            this.dataConn?.send(new SignalMessage({sender: this.userId, receiver: this.calleeId, command: Signal.HANGUP}))
        } catch (err) {
            console.error("send Signal.HANGUP出现异常。 err = "+err)
        }
        this.close();
    }

    close() {
        if (this.dataConn) {
            this.dataConn.close();
        }
        if (this.conn) {
            this.conn.close();
        }
        this.conn = null;
        this.dataConn = null;
    }

}

/**
 * 接收者
 */
class Callee {
    userId: string; // 自己的id
    callerId: string; // 呼叫人的id
    dataConn?: DataConnection;
    conn?: MediaConnection;
    localStream?: MediaStream;
    contact: any;// 对方的基本信息（name、头像等）

    constructor(userId: string, dataConn: DataConnection /*, contact: any*/) {
        this.userId = userId; // 自己的id
        this.dataConn = dataConn;
        this.conn = null;
        this.localStream = null;
        this.callerId = dataConn.peer; // 呼叫人的id

        // this.contact = contact;
    }

    /**
     * 接听
     */
    accept(localStream: MediaStream) {
        this.dataConn?.send(new SignalMessage({sender: this.userId, receiver: this.callerId, command: Signal.ACCEPT}))
        this.localStream = localStream;
    }

    /**
     * 拒接
     */
    reject() {
        this.dataConn.send(new SignalMessage({sender: this.userId, receiver: this.callerId, command: Signal.REJECT}))
    }

    /**
     * 开始通话
     * @param remoteVideo
     * @param mediaConn
     */
    answerTalk(remoteVideo: any, mediaConn: MediaConnection) {
        mediaConn.answer(this.localStream);
        this.conn = mediaConn;
        let streamId = null;
        mediaConn.on('stream', (stream) => {
            if (stream.id !== streamId) {
                streamId = stream.id;
                console.debug(`>>> 远端流 stream.id=${stream.id}. 是否含有音轨? ${hasAudioTrack(stream)} `)
                //播放远端的stream
                remoteVideo.srcObject = stream;
                // 监听canplay事件，确保媒体就绪后再播放
                remoteVideo.addEventListener('canplay', () => {
                    remoteVideo.play().catch(err => {
                        console.error('播放错误:', err);
                    });
                });
            } else {
                console.debug(`>>> 远端流重复 stream.id=${stream.id}. 是否含有音轨? ${hasAudioTrack(stream)} `)
            }
        });
    }

    hangup() {
        try{
            this.dataConn?.send(new SignalMessage({sender: this.userId, receiver: this.callerId, command: Signal.HANGUP}))
        } catch (err) {
            console.error("send Signal.HANGUP出现异常。 err = "+err)
        }
        this.close();
    }

    close() {
        if (this.dataConn) {
            this.dataConn.close();
        }
        if (this.conn) {
            this.conn.close();
        }
        this.conn = null;
        this.dataConn = null;
    }

}


export {
    CallStatus,
    Signal,
    Caller,
    Callee,
}